home *** CD-ROM | disk | FTP | other *** search
- /*
- CDOpen - An XCMD to open the .AppleCD driver for use by HyperCard.
- ©Apple Computer, Inc. 1988
- All Rights Reserved.
-
- 88/10/08 BL°B First Version
-
- To compile and link this file using Macintosh Programmer's Workshop,
-
- C -q2 CDOpen.c
- link -sn Main=CDOpen -sn STDIO=CDOpen ∂
- -sn INTENV=CDOpen -rt XFCN=42 ∂
- -m CDOpen CDOpen.c.o "{CLibraries}"CRuntime.o ∂
- "{CLibraries}"CInterface.o ∂
- -o HyperCommands
-
- This link directive puts the XCMD in the file "HyperCommands".
- Substitute the name of the stack you want it in. To move XCMDs
- between stacks, use ResEdit. They can be in an individual stack,
- the Home stack, the HyperCard application, or the System File.
-
- */
-
- #include <cd.h>
- #include <SysEqu.h>
- #include <strings.h>
-
- #define dRAMBased 0x40 /* bit 6 -- see IM II-190 */
-
- /* prototype definitions for functions */
- OSErr GetVolStuff(short, short *, short *, StringPtr);
- Boolean IsItCD(short, StringPtr);
- OSErr StartAtTrack1(short);
- OSErr AStatus(short, short *);
- void pStrCpy(char *, char *);
- Boolean pStrCmp(StringPtr, StringPtr);
-
- /* **** WARNING: DO NOT USE GLOBAL VARIABLES! **** */
-
-
- /************************************************************************
- *
- * Function: CDOpen
- *
- * Purpose: Open the driver and return the ioRefNum
- *
- * Returns: ioRefNum (used for subsequent calls to driver)
- *
- * Side Effects: none
- *
- * Description: We normally don't need any parameters. If you have
- * several CD SC drives attached, we will accept a
- * single parameter which is the SCSI ID of the drive.
- * We cruise through the volume chain, trying to find
- * an audio CD volume. When we find it, we return both
- * the vRefNum and dRefNum, concatenated together and
- * converted into a string.
- *
- ************************************************************************/
- pascal void
- CDOpen(paramPtr)
- XCmdBlockPtr paramPtr;
- {
- Str31 returnString;
- OSErr result;
- short dRefNum;
- short vRefNum;
- long bothRefNums;
- short driveNumber;
- short status;
- Str255 driverName;
- Handle playModeHandle;
-
- /* Must be no parameters or one parameters */
- if ( paramPtr->paramCount > 1)
- {
- /* Report error in parameters by returning -1 */
- NumToStr(paramPtr, (long) -1, returnString);
- paramPtr->returnValue = PasToZero(paramPtr, (StringPtr) returnString);
- return;
- }
-
- if ( paramPtr->paramCount == 1)
- driveNumber = atoi(*(paramPtr->params[0]));
- else
- driveNumber = -1; /* -1 says "open first available" */
-
- GetIndString(driverName, STR_ID, DRIVER_STR);
- if (driverName == nil)
- result = ResError();
-
- result = GetVolStuff(driveNumber, &dRefNum, &vRefNum, driverName);
-
- if (result == noErr)
- {
- AStatus(dRefNum, &status);
- if (status > 3) /* not playing; seek to track 1 */
- StartAtTrack1(dRefNum);
- /* we must ignore any possible error coming back from StartAtTrack1(),
- ** because the first track might be data, and this will give us a paramErr.
- */
- }
-
- /* Concatentate vRefNum & dRefNum, convert to string & return it */
- if (result == noErr)
- bothRefNums = (long)vRefNum << 16 | ((long)dRefNum & 0x0000FFFF);
- else
- bothRefNums = 0;
-
- NumToStr(paramPtr, (long) bothRefNums, returnString);
- paramPtr->returnValue = PasToZero(paramPtr, (StringPtr) returnString);
-
- SetGlobal(paramPtr, GLOBALNAME, paramPtr->returnValue);
- playModeHandle = PasToZero(paramPtr, "\p9");
- SetGlobal(paramPtr, PLAYMODE, playModeHandle);
- DisposHandle(playModeHandle);
- }
-
-
- /************************************************************************
- *
- * Function: GetVolStuff
- *
- * Purpose: get volume reference number for audio CD
- *
- * Returns: OSErr
- * noErr if we found an audio volume
- * nsvErr if no such volume was mounted
- * (may return other errors if problem with system)
- *
- * Side Effects: fills in vRefNum
- *
- * Description: using the PBHGetVInfo call documented on pages IV-129
- * and IV-130 of IM v4, we loop through the list of
- * mounted volumes. For each volume that we find, check
- * to see if it's a CD (using IsItCD). If it is a CD,
- * check and see if it's the SCSI ID. If it
- * is the right SCSI ID, return the vRefNum and dRefNum
- * that is associated with that volume.
- * If we are passed a SCSI ID of -1, it means "open the
- * first CD we find."
- *
- ************************************************************************/
- OSErr
- GetVolStuff(scsiID, dRefNum, vRefNum, driverName)
- short scsiID; /* which CD drive to find */
- short *dRefNum; /* driver reference number */
- short *vRefNum; /* volume reference number */
- StringPtr driverName; /* name of the driver we're comparing against */
- {
- short i;
- OSErr result;
- Boolean foundIt;
- short currentScsiID;
- HVolumeParam hParamBlock;
-
- result = noErr;
- foundIt = false;
-
- for (i = 1; result != nsvErr && foundIt == false; i++)
- {
- hParamBlock.ioCompletion = 0;
- hParamBlock.ioNamePtr = nil;
- hParamBlock.ioVRefNum = 0;
- hParamBlock.ioVolIndex = i;
- result = PBHGetVInfo(&hParamBlock,false);
- if (IsItCD(hParamBlock.ioVDRefNum, driverName) == true)
- {
- if (scsiID == -1)
- foundIt = true; /* find anything if asked for -1 */
- else
- {
- currentScsiID = (-hParamBlock.ioVDRefNum) - 32 -1;
- if (currentScsiID == scsiID)
- foundIt = true;
- }
- }
- }
- if (result == noErr)
- {
- *dRefNum = hParamBlock.ioVDRefNum;
- *vRefNum = hParamBlock.ioVRefNum;
- }
-
- return result;
- }
-
- /************************************************************************
- *
- * Function: IsItCD
- *
- * Purpose: determine if this driver reference number points to
- * a CD or not.
- *
- * Returns: Boolean
- * true = this dRefNum points to a CD
- * false = this dRefNum points to something else
- *
- * Side Effects: none
- *
- * Description: The unit table points to the device control entry.
- * The device control entry contains either a pointer
- * to a ROM based driver or a handle
- * to a RAM based driver. The driver has the
- * name starting at byte offset 18. All this stuff
- * is documented in Inside Mac, II-187 through II-192
- * and IV-215
- *
- * Note that the Apple CD-ROM driver claims to be ROM
- * based(!), but third party drivers such as OMI's
- * correctly claim to be RAM based.
- *
- * Check out the driver name and see if it matches the
- * driver name we're passed. If it does, this is a CD.
- *
- ************************************************************************/
- Boolean
- IsItCD(dRefNum, driverName)
- short dRefNum;
- StringPtr driverName;
- {
- Boolean result;
- DCtlHandle dCtlHandle;
- StringPtr driverNamePtr;
- Handle driverHandle;
-
- result = false; /* assume not a CD */
-
- dCtlHandle = GetDCtlEntry(dRefNum);
-
- if ((**dCtlHandle).dCtlFlags & dRAMBased)
- {
- driverHandle = (Handle) (**dCtlHandle).dCtlDriver;
- driverNamePtr = (char *) *driverHandle+18; /* magic number! */
- }
- else
- driverNamePtr = (char *) (**dCtlHandle).dCtlDriver+18; /* magic number! */
- /* offset of driver name in device control entry. */
-
- if (pStrCmp(driverNamePtr, driverName))
- result = true; /* this is a CD */
- return result;
- }
-
-
- /************************************************************************
- *
- * Function: StartAtTrack1
- *
- * Purpose: start Searching an audio track
- *
- * Returns: OSErr. Probably either
- * noErr everything's hunky-dory!
- * paramErr you messed up the call somehow.
- *
- * Side Effects: starts search.
- *
- * Description: The track that you pass in is the location to which
- * you want to search. You can then start play with
- * a pause command.
- *
- ************************************************************************/
- OSErr
- StartAtTrack1(refNum)
- short refNum;
- {
- CDParam myPB;
-
- myPB.ioCompletion = 0;
- myPB.ioNamePtr = (char *) 0;
- myPB.ioVRefNum = 1;
- myPB.ioCRefNum = refNum;
- myPB.csCode = ASEARCH;
-
- myPB.csParam[0] = 0;
- myPB.csParam[1] = TRACKADDR;
- myPB.csParam[2] = 0;
- myPB.csParam[3] = 0;
- myPB.csParam[4] = 0;
- myPB.csParam[5] = 1; /* search to track 1 */
- myPB.csParam[6] = 0;
- myPB.csParam[7] = 0; /* search and pause */
- myPB.csParam[8] = 0;
- myPB.csParam[9] = STEREO;
- return (PBControl(&myPB, false));
- }
-
- /************************************************************************
- *
- * Function: AStatus
- *
- * Purpose: return CD audio status
- *
- * Returns: OSErr. Probably either
- * noErr everything's hunky-dory!
- * paramErr you messed up the call somehow.
- *
- * Side Effects: modifies "status" to reflect the audio status byte
- * returned by the driver.
- *
- * Description: Simply call the driver and return the audio status
- * byte that the driver gives us.
- *
- ************************************************************************/
- OSErr
- AStatus(refNum, status)
- short refNum;
- short *status;
- {
- CDStatusParam myPB;
- OSErr result;
-
- myPB.ioCompletion = 0;
- myPB.ioNamePtr = (char *) 0;
- myPB.ioVRefNum = 1;
- myPB.ioCRefNum = refNum;
- myPB.csCode = ASTATUS;
-
- result = PBControl(&myPB, false);
- *status = (short) myPB.audioStatus;
- return result;
- }
-
-
-
- /************************************************************************
- *
- * Function: pStrCpy
- *
- * Purpose: copy a pascal string.
- *
- * Returns: nothing
- *
- * Side Effects: 'dest' contents are changed.
- *
- * Description:
- *
- *
- ************************************************************************/
- void
- pStrCpy(src, dest)
- char *src;
- char *dest;
- {
- short i;
- short length;
-
- length = src[0];
-
- for (i = 0; i <= length; i++)
- dest[i] = src[i];
- }
-
-
- /************************************************************************
- *
- * Function: pStrCmp
- *
- * Purpose: compare 2 pascal string.
- *
- * Returns: true if equal, false if not
- *
- * Side Effects: none
- *
- * Description:
- *
- *
- ************************************************************************/
- Boolean
- pStrCmp(src, dest)
- StringPtr src;
- StringPtr dest;
- {
- short length;
-
- length = src[0];
-
- while (length--)
- if (*src++ != *dest++)
- return false;
- return true;
- }
-
- #include <XCmdGlue.inc.c>
-